package pl.enigmatic.input;

import java.awt.Graphics;

import javax.swing.JTextField;

import pl.enigmatic.awt.Frames;
import pl.enigmatic.math.MathUtil;
import pl.enigmatic.util.Strings;


public class DoubleInput extends JTextField {

	/** */
	private static final long serialVersionUID = 1L;

	private double value;

	private final double min;
	private final double max;
	private final double step = 0.1;

	public DoubleInput(final double min, final double max) {
		this.min = min;
		this.max = Math.max(min, max);
		setValue(0.0);
		new MouseValueIncreaser(new MouseValueIncreaser.Target() {

			@Override
			public void increaseValue(final int steps) {
				setValue(value + step * steps);
			}
		}).applyTo(this);
	}

	public DoubleInput() {
		this(-Double.MAX_VALUE, Double.MAX_VALUE);
	}

	private double parse(String string) {
		if (Strings.nonEmpty(string)) {
			try {
				final boolean minus = string.startsWith("-");
				string = minus ? string.substring(1) : string;
				final String[] split = string.split("\\.");
				string = minus ? "-" : "";
				string += split.length > 0 ? split[0].replaceAll("[^1234567890]", "") : 0;
				string += ".";
				string += split.length > 1 ? split[1].replaceAll("[^1234567890]", "") : 0;
				final double x = MathUtil.clamp(min, max, Double.parseDouble(string));
				return x;
			} catch (final Exception e) {}
		}
		return value;
	}

	@Override
	protected void paintComponent(final Graphics g) {
		final String txt = getText();
		final double v = parse(txt);
		if ("-".equals(txt) || ".".equals(txt) || "-.".equals(txt) || "".equals(txt)) {
			_setValue(0);
			setTextSuper(txt);
		} else if (!(txt.startsWith("-") || txt.startsWith(".") || Strings.isNumeric(txt.substring(0, 1)))
				&& (txt.startsWith("-.") || Strings.isNumeric(txt.substring(0, 2)))) {
			setTextSuper("");
		} else {
			_setValue(v);
		}
		super.paintComponent(g);
	}

	@Override
	public void setText(final String t) {}

	private void setTextSuper(final String t) {
		if (!t.equals(getText())) {
			final int start = getSelectionStart();
			final int end = getSelectionEnd();
			super.setText(t);
			setSelectionStart(Math.max(start, 0));
			setSelectionEnd(Math.max(end, 0));
		}
	}

	private void _setValue(final double value) {
		final double old = this.value;
		this.value = value;
		setTextSuper(Double.toString(this.value));
		if (old != value) {
			onValueChanged(old);
		}
	}

	protected void onValueChanged(final double old) {}

	public void setValue(final double value) {
		_setValue(MathUtil.clamp(min, max, value));
		repaint();
	}

	public double getValue() {
		return value;
	}

	public double getStep() {
		return step;
	}

	public static void main(final String[] args) {
		Frames.show(new DoubleInput());
	}

}
